package com.spx;


import com.spx.SpriteXData.SpxAction;


public class SpriteX2 extends Layer implements LTrans{
	public static final int SPX_FLOAT_UNIT=10000;
	public static final int SPX_PLAY_NORMAL=0x01;
	public static final int SPX_PLAY_BACK=0x02;
	public static final int SPX_STOP_END=0x04;
	public static final int SPX_STOP_START=0x08;
	public static final int SPX_END_NO_VISIBLE=0x10;
	
	/**
	 * SPX 数据
	 */
	private SpriteXData spx;
	int transform;
	private int actionIndex;
	private int sequenceIndex;
	private int lastUpdateTime;
	private int delay;
	private int playCount;
	
	private boolean playing;
	private boolean isPause;
	private int playParam;
	private int startSequenceIndex;
	private int pauseTimeOffset;
	
	
	public SpriteX2(SpriteXData spx){
		if(spx==null)
			throw new NullPointerException("SpriteXData is null!");
		playCount=1;
		visible=true;
		this.spx=spx;
	}

	/**
	 * 获得SPX 数据
	 * @return
	 */
	public SpriteXData getSpriteX(){
		return spx;
	}

	/**
	 * 获得当前动作帧标志
	 * @return
	 */
	public final int getFlagBits(){
		return spx.getSpxFrame(getSequenceFrameIndex()).flagBits;
	}

	public void setActionFromIndex(int actionIndex){
		if(actionIndex<0||actionIndex>=spx.getActionCount()){
			throw new IndexOutOfBoundsException("actionIndex:"+actionIndex+"越界！");
		}
        this.sequenceIndex=0;
		this.actionIndex=actionIndex;
	}

	/**
	 * 获得动画数量
	 * @return
	 */
	public int getActionCount(){
		return spx.getActionCount();
	}

	/**
	 * 获得当前动画的动作帧数量
	 * @return
	 */
	public final int getSequenceCount(){
		return spx.actions[actionIndex].frameSequences.length;
	}

	public final int getSequenceIndex(){
		return sequenceIndex;
	}
	
	/*当前动作是否播放完毕*/
	public boolean isActionFinish(){
		if(sequenceIndex >= spx.actions[actionIndex].frameSequences.length-1)
			return true;
		else
			return false;
	}

	/**
	 * 获得当前动作帧
	 * @return
	 */
	public final int getSequenceFrameIndex(){
		return spx.actions[actionIndex].frameSequences[sequenceIndex];
	}

	public final void setSequenceIndex(int sequenceIndex){
		if(sequenceIndex<0||sequenceIndex>=spx.actions[actionIndex].frameSequences.length){
			return;
		}
		this.sequenceIndex=sequenceIndex;
	}

	private final void nextFrame(){
		sequenceIndex= (sequenceIndex+1) % getSequenceCount();
	}

	/**
	 * 设置帧延时（追加动画帧延时）
	 * @param delay
	 */
	public final void setDelay(int delay){
		this.delay=delay;
	}

	/**
	 * 获得设置延时
	 * @return
	 */
	public final int getDelay(){
		return delay;
	}

	/**
	 * 获得实时延时
	 * @return
	 */
	public final int getSequenceDelay(){
		SpxAction action=spx.actions[actionIndex];
		if(action.mode==SpxAction.SPX_DELAY){
			return delay+action.frameDelays[sequenceIndex];
		}
		return delay;
	}
	
	public void paintLayer(LGraphics g) {
		if(!visible)return;
		spx.drawFrame(this,g,x,y,actionIndex,sequenceIndex);
	}

	/**
	 * 画图像区域
	 * @param image        图像源
     * @param x_src        区域X
     * @param y_src        区域Y
     * @param width        区域WITH
     * @param height       区域HEIGHT
     * @param transform    翻转
     * @param x_dest       绘制位置X 
     * @param y_dest       绘制位置Y
	 */
	protected void drawRegion(LGraphics context,Image image,int x_src,int y_src,int width,int height,int transform,
			int x_dst,int y_dst){
		context.drawRegion(image, x_src, y_src, width, height, transform, x_dst, y_dst,0);
	}
	
	public void setTransform(int transform){
		this.transform=transform;
	}

	public int getTransform(){
		return transform;
	}

	public void rotate90D(){
		transform=LTrans.ROTATE_TABLE[transform][1];
	}

	public void rotate90A(){
		transform=LTrans.ROTATE_TABLE[transform][0];
	}

	public void mirrorH(){
		transform=LTrans.ROTATE_TABLE[transform][2];
	}

	public void mirrorV(){
		transform=LTrans.ROTATE_TABLE[transform][3];
	}

	/**
	 * 动画播放设置  （-1 循环  0 停止   大于0   播放次数）
	 * @param playCount
	 */
	public void setPlayCount(int playCount){
		if(playing){
			return;
		}
		this.playCount=playCount;
	}

	public int getPlayCount(){
		return playCount;
	}

	public void play(){
		play(SPX_PLAY_NORMAL|SPX_STOP_END,0);
	}

	public boolean play(int param,int startSequenceIndex){
		if(isPause){
			pause();
			return true;
		}
		if(playCount==0){
			return false;
		}
		if(startSequenceIndex<0||startSequenceIndex>=getSequenceCount()){
			return false;
		}
		if(playing){
			return false;
		}
		setSequenceIndex(startSequenceIndex);
		this.startSequenceIndex=startSequenceIndex;
		playParam=param;
		lastUpdateTime=getTimeMillis();
		playing=true;
		return true;
	}

	public void pause(){
		if(!playing){
			return;
		}
		int nowTime=getTimeMillis();
		if(isPause){
			pauseTimeOffset=nowTime-lastUpdateTime;
		}else{
			lastUpdateTime=nowTime+pauseTimeOffset;
		}
		isPause=!isPause;
	}

	public void stop(){
		playing=false;
		isPause=false;
		playCount=1;
	}
	
	private final static int getTimeMillis(){
		return (int)(System.currentTimeMillis()&0x7fffffff);
	}
	
	public boolean isPlay(){
		return playing;
	}

	public boolean isPause(){
		return isPause;
	}

	public void update(){
		update(getTimeMillis());
	}

	private final void update(int nowTime){
		if(!update||!playing||isPause){
			return;
		}
		if(nowTime-lastUpdateTime>=getSequenceDelay()){
			if((playParam&SPX_PLAY_NORMAL)!=0){
				nextFrame();
			}
			if(getSequenceIndex()==startSequenceIndex){
				if(playCount>0){
					--playCount;
				}
				if(playCount==0){
					stop();
				}
			}
			lastUpdateTime=nowTime;
		}
		if(!isPlay()){
			if((playParam&SPX_STOP_START)!=0){
				setSequenceIndex(startSequenceIndex);
			}else if((playParam&SPX_STOP_END)!=0){
				setSequenceIndex(getSequenceCount()-1);
			}
			if((playParam&SPX_END_NO_VISIBLE)!=0){
				setVisible(false);
			}
		}
	}

	/**
	 * 获得当前动作帧矩形碰撞数量
	 * @return
	 */
	public final int getFrameCollideCount(){
		return spx.getSpxFrame(getSequenceFrameIndex()).collides.length;
	}

	/**
	 * 获得当前动作帧指定的矩形碰撞
	 * @param collideIndex	索引
	 * @return
	 */
	public final SpxRect getFrameCollideFromIndex(int collideIndex){
		if(collideIndex<0||collideIndex>=getFrameCollideCount()){
			return null;
		}
		SpxRect rect=new SpxRect(spx.getSpxFrame(getSequenceFrameIndex()).collides[collideIndex]);
		rect.transform(transform);
		rect.translate(x,y);
		return rect;
	}
}